﻿using Microsoft.Extensions.DependencyInjection;
using SqlSugarAndEntity;
using SqlSugarAndEntity.Entity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Utils;

namespace Reptile
{
    internal class Data
    {
        private readonly IBaseMethod SqlSugarProvider;
        public Data()
        {
            IServiceCollection services = new ServiceCollection();
            services.AddSingleton<IBaseMethod, BaseMethod>();
            IServiceProvider serviceProvider = services.BuildServiceProvider();
            SqlSugarProvider = serviceProvider.GetService<IBaseMethod>();
        }
        public void Execute(Dictionary<string,string> TypeAndName) 
        {
            string CatalogBaseUrl = "https://news.cqu.edu.cn/archives/{0}{1}";
            string BaseUrl = "https://news.cqu.edu.cn";
            foreach (string Type in TypeAndName.Keys)
            {
                string CatalogListUrl=string.Format(CatalogBaseUrl,Type,"/index.html" );
                int total = GetTotalPage(CatalogListUrl);
                for(int i = 1; i < total; i++)
                {
                    string ListUrl = string.Empty;
                    if (i == 1)
                    {
                        ListUrl = CatalogListUrl;
                    }
                    else
                    {
                        ListUrl = string.Format(CatalogBaseUrl, Type, $"/list/{i}.html");
                    }
                    var Urls = GetDetailIds(ListUrl);
                    var result = GetDetail(TypeAndName[Type], BaseUrl, Urls);
                    if (result.newslist.Count > 0)
                    {
                        SqlSugarProvider.Db().Insertable(result.newslist).AddSubList(t => t.newsfiles).ExecuteCommand();
                    }
                    
                    if (!result.IsContinue)
                    {
                        break;
                    }
                }
            }
        }
        /// <summary>
        /// 获取总页数
        /// </summary>
        /// <param name="ListPageUrl"></param>
        /// <returns>总页数</returns>
        public int GetTotalPage(string ListPageUrl)
        {
            var html= HttpRequestHelper.ClientGetString(ListPageUrl);
            Regex PageDivReg = new Regex("<div class=\"page\">.*</div>");
            var res = PageDivReg.Match(html).ToString();
            var p = GetTitleContent(res, "a", MathIndex =>
            {
                return MathIndex - 1;
            });
            return Convert.ToInt32(p);

        }
        /// <summary>
        /// 获取列表页list的详情地址连接
        /// </summary>
        /// <param name="ListPageUrl">列表页url</param>
        /// <returns>详情页相对路径集合</returns>
        public List<string> GetDetailIds(string ListPageUrl)
        {
            List<string> list = new List<string>();
            var html = HttpRequestHelper.ClientGetString(ListPageUrl);
            //匹配class为item的
            Regex PageDivReg1 = new Regex("<div class=\"item\">[\\s]\\D+.+[\\s]\\D+.+[\\s]\\D+.+[\\s]</div>\\D+.+");
            //匹配class为title的
            Regex PageDivReg2 = new Regex("<div class=\"title\">[\\s]\\D+.+");
            var res=PageDivReg1.Matches(html);
            foreach (var item in res)
            {
                if (item != null)
                {

                    var DetailHtml = PageDivReg2.Match(item.ToString()).ToString();
                    DetailHtml = DetailHtml
                        .Replace("\n","")
                        .Replace("\t","")
                        .Replace("<div class=\"title\">", "");
                    string DetailID = GetTitleContent(DetailHtml, "a", "href");
                    list.Add(DetailID);
                }
            }
            return list;
        }
        /// <summary>
        /// 获取详情页内的所有内容
        /// </summary>
        /// <param name="NewType">新闻类型</param>
        /// <param name="BaseUrl">根目录</param>
        /// <param name="urls">详情页相对路径集合</param>
        /// <returns>新闻实体类</returns>
        public (bool IsContinue,List<news> newslist) GetDetail(string NewType,string BaseUrl,List<string> urls)
        {
            List<news> newsList = new List<news>();
            //获取作者的表达式内容块
            Regex Author = new Regex("<div class=\"dinfoa\" >[\\s]\\D.+.+");
            //获取A标签
            Regex Rega = new Regex("<a href=.*</a>");
            //标题正则
            Regex Title = new Regex("<h1 class=\"dtitle\">.*</h1>");
            //日期正则
            Regex DateReg = new Regex("<div class=\"ibox\">[\\s]\\D.+.+[\\s]\\D.+.+[\\s]\\D.+.+</div>");
            //摘要正则
            Regex adetail = new Regex("<div class=\"adetail\">[\\s]\\D.+.+[\\s]\\D.+.+[\\s]\\D.+.+</div>");
            Regex ContentReg = new Regex("<div class=\"acontent\">[\\s]\\D.+.+[\\s]\\D.+.+</div>");
            string FileSavePath = $"{Directory.GetCurrentDirectory().Replace("\\", "/").Split(new string[] { "/bin/" }, StringSplitOptions.None)[0]}/File/";
            foreach (string url in urls)
            {
                news news = new news();

                news.Type = NewType;
                var RequestPath = BaseUrl + url;
                //获取详情页的所有内容
                var html =HttpRequestHelper.ClientGetString(RequestPath);
                //日期获取
                var DateHtml = DateReg.Match(html).ToString();
                news.PublishTime = Convert.ToDateTime(GetTitleContent(DateHtml, "span", index =>
                {
                    return index;
                }));
                //新闻id
                news.ID = url.Split("/")[url.Split("/").Length - 1].Split(".")[0];
                news.RequestPath = RequestPath;
                //作者
                var AuthorHtml=Author.Match(html).ToString();
                AuthorHtml= Rega.Match(AuthorHtml).ToString();
                news.Author = GetTitleContent(AuthorHtml, "a");
                //标题
                var TitleHtml=Title.Match(html).ToString();
                news.Title = GetTitleContent(TitleHtml, "h1");
                //摘要
                var AbstHtml = adetail.Match(html).ToString();
                news.Abstract = GetTitleContent(AbstHtml, "div").Replace("\n","").Trim();
                var ContentHtml = ContentReg.Match(html).ToString();
                var ImageList = GetHtmlImageUrlList(ContentHtml);
                var ContentStr = RemoveAllHtml(ContentHtml);
                news.Content= ContentStr;
                if (ImageList.Count > 0)
                {
                    news.newsfiles = new List<newsfile>();
                    foreach(string path in ImageList)
                    {
                        string FileName = path.Split("/")[path.Split("/").Length - 1];
                        HttpRequestHelper.ClientGetDownload("https://news.cqu.edu.cn" + path, FileSavePath+ FileName);
                        newsfile item = new newsfile()
                        {
                            ID = Guid.NewGuid().ToString(),
                            FileRequestPath = "https://news.cqu.edu.cn" + path,
                            FileName = FileName,
                            NewsID = news.ID
                        };
                        news.newsfiles.Add(item);
                    }
                }
                newsList.Add(news);
            }
            return (true,newsList);
        }

        #region 私有帮助方法
        /// <summary>
        /// 获取标签内的文字
        /// </summary>
        /// <param name="str">html</param>
        /// <param name="title">标签</param>
        /// <param name="MatchIndexFunc">多个匹配时,要匹配的索引委托</param>
        /// <returns>标签内的文字</returns>
        private string GetTitleContent(string str, string title, Func<int, int> MatchIndexFunc = null)
        {
            if (str == null || str == "")
            {
                return "";
            }
            int index = 0;
            string tmpStr = string.Format("<{0}[^>]*?>(?<Text>[^<]*)</{0}>", title); //获取<title>之间内容

            var TitleMatch = Regex.Matches(str, tmpStr, RegexOptions.IgnoreCase);
            if (MatchIndexFunc != null)
            {
                index = MatchIndexFunc.Invoke(TitleMatch.Count - 1);
            }

            string result = TitleMatch[index].Groups["Text"].Value;
            return result;
        }
        /// <summary>
        /// 获取html的标签内的特性
        /// </summary>
        /// <param name="str">html文本</param>
        /// <param name="title">标签名</param>
        /// <param name="attrib">特性名</param>
        /// <returns>特性值</returns>
        private static string GetTitleContent(string str, string title, string attrib)
        {
            if (str == null || str == "")
            {
                return "";
            }
            string tmpStr = string.Format("<{0}[^>]*?{1}=(['\"\"]?)(?<url>[^'\"\"\\s>]+)\\1[^>]*>", title, attrib); //属性值

            Match TitleMatch = Regex.Match(str, tmpStr, RegexOptions.IgnoreCase);

            string result = TitleMatch.Groups["url"].Value;
            return result;
        }
        /// <summary>    
        /// 取得HTML中所有图片的 URL。    
        /// </summary>    
        /// <param name="sHtmlText">HTML代码</param>    
        /// <returns>图片的URL列表</returns>    
        private static List<string> GetHtmlImageUrlList(string sHtmlText)
        {
            List<string> result = new List<string>();
            if (string.IsNullOrEmpty(sHtmlText))
            {
                return result;
            }
            // 定义正则表达式用来匹配 img 标签    
            Regex regImg = new Regex(@"<img\b[^<>]*?\bsrc[\s\t\r\n]*=[\s\t\r\n]*[""']?[\s\t\r\n]*(?<imgUrl>[^\s\t\r\n""'<>]*)[^<>]*?/?[\s\t\r\n]*>", RegexOptions.IgnoreCase);
            // 搜索匹配的字符串    
            MatchCollection matches = regImg.Matches(sHtmlText);
            // 取得匹配项列表    
            foreach (Match match in matches)
            {
                result.Add(match.Groups["imgUrl"].Value);
            }

            return result;
        }
        /// <summary>
        /// 去除所有html标签
        /// </summary>
        /// <param name="html">html文本</param>
        /// <returns>去掉全部html标签的文本</returns>
        private string RemoveAllHtml(string html)
        {
            string regexstr = @"<[^>]*>";
            return Regex.Replace(html, regexstr, string.Empty, RegexOptions.IgnoreCase).Replace("/n", "").Trim();
        }
        #endregion
    }
}
